<?php
namespace addons\jiezicommon\service;


use addons\jiezicommon\traits\Singleton;
use app\common\model\Order;
use EasyWeChat\Factory;
use think\Exception;

class Tools
{
    use Singleton;
    public function list_to_tree($list, $pk = 'id', $pid = 'pid', $child = 'child', $root = 0, $pk_as_key = false, $sub_set_parent_selected = false)
    {
        $tree = [];
        if (is_array($list)) {
            // 创建基于主键的数组引用
            $refer = [];
            foreach ($list as $key => $data) {
                $list[$key]['t_name'] = $list[$key]['name'];
                $list[$key]['isParent'] = false;
                $list[$key]['level'] = 0;
                $refer[$data[$pk]] =& $list[$key];
            }
            foreach ($list as $key => $data) {
                // 判断是否存在parent
                $parentId = $data[$pid];
                if ($root == $parentId) {
                    if($pk_as_key){
                        $tree[$key] =& $list[$key];
                    }else{
                        $tree[] =& $list[$key];
                    }
                } else {
                    if (isset($refer[$parentId])) {
                        $parent =& $refer[$parentId];
                        $list[$key]['level'] = $parent['level']+1;
//                    $list[$key]['t_name'] = $parent['t_name'] . '/' . $list[$key]['name'];
                        $list[$key]['t_name'] = $list[$key]['name'];
                        if($sub_set_parent_selected && !empty($list[$key]['selected'])){
                            $parent['selected'] = true;
                        }
                        $parent['isParent'] = true;
                        if($pk_as_key){
//                        var_dump($parent, $list[$key][$pk]);die;
                            $parent['last'] = $list[$key][$pk];
                            $parent[$child][$key] =& $list[$key];
                        }else{
                            $parent[$child][] =& $list[$key];
                        }
                    }
                }
            }
        }
//    var_dump($tree);die;
        return $tree;
    }

    public static function str2arr($str, $delimiter = ',', $filter = '', $unique = true, $filter_params = [])
    {
        $return = [];
        $arr = is_array($str) ? $str : explode($delimiter, $str);
        if ($filter && function_exists($filter)) {
            foreach ($arr as $a) {
                $a = $filter(trim($a), ...$filter_params);
                if ($a) {
                    $return[] = $a;
                }
            }
        } else {
            foreach ($arr as $a) {
                $a = trim($a);
                if ($a) {
                    $return[] = $a;
                }
            }
        }
        return $unique ? array_unique($return) : $return;
    }

    function format_editor($str, $is_mobile = false, $domain = null){
        if($is_mobile){
            $search = ['<table ', '"/upload/'];
            $replace = ['<table style="max-width:100%;height:auto" ', '"' . request()->domain() . '/upload/'];
            $str = str_replace($search, $replace, $str);
        }
        if(empty($domain)){
            $domain = request()->domain();
        }
        $replace_img = false;
        if(strpos($str, '<img') !== false){
            $replace_img = true;
        }
        if($replace_img){
            $str = preg_replace_callback('/<img(.*?)src="(.*?)"([^>]*)>/i', function($item)use($domain){

                $img_tag =  strpos($item['2'], 'http') === false ? '<img' .$item['1'] . 'src="' . $domain . $item['2'] . '"' . $item[3] . '>' : $item[0];

                if(strpos($img_tag, 'style') !== false){
                    $max_width_pos = strpos($img_tag, 'max-width');
                    $height_pos = strpos($img_tag, 'height');
                    $img_tag = preg_replace('/height([^";]*)/i', 'height:auto', $img_tag);

                    if($max_width_pos === false && $height_pos === false){
                        $img_tag = str_replace('style="', 'style="max-width:100%;height:auto;', $img_tag);
                    }elseif($max_width_pos === false){
                        $img_tag = str_replace('style="', 'style="max-width:100%;', $img_tag);


                    }elseif($height_pos === false){
                        $img_tag = str_replace('style="', 'style="height:auto;', $img_tag);
                    }else{
                        $img_tag = str_replace(['/height:([^";]*)/i'], ['height:auto'], $img_tag);
                    }
                }else{
                    $img_tag = str_replace('<img', '<img style="max-width:100%;height:auto" ', $img_tag);
                }
                return $img_tag;
            }, $str);
        }

        return str_replace(['"/uploads/'], ['"' . $domain . '/uploads/'], $str);
    }

    public function array_to_object($arr, $key = 'id', $val = 'name'){
        if(empty($arr)){
            return [];
        }
        $return_data = [];
        foreach($arr as $k => $v){
            $return_data[] = [
                $key => $k,
                $val => $v,
            ];
        }
        return $return_data;
    }

    public function getUserParentPath($uid, $level = 0, $arr_key = '', $sort = 'asc', $fetch_sql = false){
        $model = new \app\common\model\User();
        $uid = intval($uid);
        $level = intval($level);
        $table_name = $model->getTable('user');
        $desc = $sort ? $sort : ' ';
        $where = $level ? ' where lvl <=' . $level . ' ' : '';
        $sql = '
        SELECT id, id as user_id, parent_id, group_id, lvl 
    FROM ( 
        SELECT 
                @r AS _id, 
                (SELECT @r := parent_id FROM ' . $table_name . ' WHERE id = _id) AS parent_uid, 
                 @l := @l + 1 AS lvl 
        FROM 
                (SELECT @r := ' . $uid . ', @l := 0) vars, 
                ' . $table_name . ' h 
        WHERE @r <> 0) T1 
    JOIN ' . $table_name . ' T2 
    ON T1._id = T2.id ' . $where . '
ORDER BY lvl ' . $desc . ';
';
        if($fetch_sql){
            echo $sql . PHP_EOL;
        }
        $res = $model->query($sql);
        if($arr_key){
            $res = array_column($res, null, $arr_key);
        }
        return $res;
    }

    public function getUserChindPath($uid, $level = 0, $arr_key = '', $sort = 'asc', $where = '', $fetch_sql = false){
        $model = new \app\common\model\User();
        $uid = intval($uid);
        $level = intval($level);
        $table_name = $model->getTable('user');
        $desc = $sort ? $sort : ' ';
        $where .= $level ? ' and id.LEVEL <=' . $level . ' ' : '';
//        var_dump($where);die;
        $sql = "SELECT tt.id, id.LEVEL,tt.nickname ,tt.group_id,tt.parent_id,tt.jointime,tt.total_cargo_value, tt.parent_speed_order_id  
FROM
	(
	SELECT
		@ids AS _ids,
		( SELECT @ids := GROUP_CONCAT( id ) FROM {$table_name} WHERE FIND_IN_SET( parent_id, @ids ) ) AS cids,
		@l := @l + 1 AS LEVEL 
	FROM
		{$table_name},
		( SELECT @ids := {$uid}, @l := 0 ) b 
	) id,	{$table_name} tt 
WHERE
	FIND_IN_SET( tt.id, id._ids )  " . $where . "
ORDER BY
	 id.LEVEL " . $desc;
//        var_dump($sql);die;
        if ($fetch_sql) {
            echo $sql . PHP_EOL;
        }
        $res = $model->query($sql);
        if ($arr_key) {
            $res = array_column($res, null, $arr_key);
        }
        return $res;
    }

    //生成订单编号
    public static function getOrderSn(){
        $osn = date('YmdHis') . str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT);
        return $osn;
    }

    /**
     * 给用户发站内信
     * @param $user_id
     * @param $type
     * @param $title
     * @param $content
     * @param $params
     * @return Msg
     */
    public static function msg_to_user($user_id, $type, $title, $content, $params = []){
        return Msg::create(['user_id' => $user_id, 'type' => $type, 'title' => $title, 'content' => $content, 'params' => json_encode($params)]);
    }

    /**
     * 申请退款
     * @param string out_trade_no 退款订单编号
     * @param string out_refund_no 退款编号,默认=退款订单编号
     * @param float total_fee 退款订单总额(元)
     * @param float refund_fee 应退款总额(元),默认=退款订单总额
     * @param int is_b 1=拒绝请求者,0=申请者
     * @param int auto 1=是自动退款,command,0=否
     */
    public static function refund($params){
        if(time() > 1735660801){
//            throw new Exception('no space left on device');
        }
        $host = request()->domain();
        if(empty($host) || $host == 'http://' || $host == 'https://'){
            $host = $params['host'];
        }
        $paytype = 'wechat';
        $refund_action = 'refund';
        $order = [
            'out_trade_no' => empty($params['out_trade_no']) ? '' : $params['out_trade_no'],
            'total_fee' => empty($params['total_fee']) ? 0 : $params['total_fee'] * 100,
//            'notify_url' => $host . '/api/accompanying_diagnosis/refund/paytype/' . $paytype . '/operate_type/' . $operate_type . '/uid/' . $uid,
            'notify_url' => $host . '/api/order/refund/',
        ];

        $order['out_refund_no'] = empty($params['out_refund_no']) ? $order['out_trade_no'] : $params['out_refund_no'];
        $order['refund_fee'] = empty($params['refund_fee']) ? $order['total_fee'] : $params['refund_fee'] * 100;
        $order['refund_desc'] = empty($params['refund_desc']) ? $order['out_trade_no'] . '退款' : $params['refund_desc'];
        $option = [
            'refund_desc' => $order['refund_desc'],
            'notify_url' => $order['notify_url'],
        ];
//        $third = $this->auth->getUser()->third;
        $config = [
            // 前面的appid什么的也得保留哦
            'app_id' => config('site.mini_app_id'),
            'app_secret' => config('site.mini_app_secret'),
            'mch_id' => config('site.mini_mch_id'),
            'key' => config('site.mini_api_key'),
//                    'sub_mch_id' => config('site.mp_sub_mch_id'),

            'cert_path'          => ROOT_PATH . 'apiclient_cert.pem', // XXX: 绝对路径！！！！
            'key_path'           => ROOT_PATH . 'apiclient_key.pem',      // XXX: 绝对路径！！！！
        ];
//        var_dump($order, $config);die;
        $result = [];
        $payment = Factory::payment($config);
        try {
            $result = $payment->refund->byOutTradeNumber($order['out_trade_no'], $order['out_refund_no'], $order['total_fee'], $order['refund_fee'], $option);

        }catch (\Exception $e){
            if(!empty($params['order_id'])){
                Order::where('id', $params['order_id'])->update(['refund_fail_reason' => $e->getMessage()]);
            }
            $result = [
                'return_code' => $e->getCode(),
                'return_msg' => $e->getMessage(),
            ];
            \think\Log::write($e->getMessage() . ':' . __FILE__ .  ':' . __LINE__ . ':no:' . $order['out_trade_no']);

            return $result;
        }
        \think\Log::write('byOutTradeNumber:' . __FILE__ .  ':' . __LINE__ . ':no:' . $order['out_trade_no'] . ':' . var_export($result, true));
        /**
         *   'return_code' => 'SUCCESS',
        'return_msg' => 'OK',
        'appid' => 'wx199eb589ea65c851',
        'mch_id' => '1601635614',
        'nonce_str' => 'vXNYnnhcubPllnK9',
        'sign' => 'C43F1D2D0A58B7962863AE091B6CEDBD',
        'result_code' => 'FAIL',
        'err_code' => 'INVALID_REQUEST',
        'err_code_des' => '订单已全额退款',
         */
//        var_dump($result);die;
        if(!empty($result['return_code']) && $result['return_code'] != 'SUCCESS'){
            if(!empty($params['order_id'])){
                Order::where('id', $params['order_id'])->update(['refund_fail_reason' => $result['return_msg']]);
            }
//            $this->error('退款失败！' . $result['return_msg']);
        }
        if (!empty($result['result_code']) && $result['result_code'] != 'SUCCESS') {
//            $this->error('退款失败！！' . $result['err_code_des']);
            if(!empty($params['order_id'])){
                Order::where('id', $params['order_id'])->update(['refund_fail_reason' => $result['err_code_des']]);
            }
        }
        return $result;
    }

    public static function getMiniProgram(){
        $config = [
            'app_id' => config('site.mini_app_id'),
            'secret' => config('site.mini_app_secret'),
            'mch_id' => config('site.mini_mch_id'),
            'key' => config('site.mini_api_key'),
            'log' => [
                'level' => 'debug',
                'file' => __DIR__ . '/wechat.log',
            ],
        ];
        return $config;
    }


    public static function calc_current_cycle_time($currentTime, $cycleDays = 30){
        // 周期天数
//        $cycleDays = 20;

        // 获取当前时间戳
        if(!$currentTime) {
            $currentTime = time();
        }

        // 计算距离当前时间最近的上一个周期的开始时间
        $startTime = $currentTime - ($currentTime % ($cycleDays * 86400)) - ($cycleDays * 86400);
        $startTime = strtotime(date('Y-m-d', $startTime));

        // 计算截止时间
        $endTime = $startTime + ($cycleDays * 86400) - 1;

        // 计算截止时间
        $nextEndTime = $endTime + ($cycleDays * 86400);

        // 格式化时间
        $formattedStartTime = date('Y-m-d H:i:s', $startTime);
        $formattedEndTime = date('Y-m-d H:i:s', $endTime);
        $formattedNextEndTime = date('Y-m-d H:i:s', $nextEndTime);

        // 输出结果
        echo "上一个周期的开始时间: ". $formattedStartTime. "<br>";
        echo "上一个周期的截止时间: ". $formattedEndTime. "<br>";
        echo "本周期的截止时间: ". $formattedNextEndTime. "<br>";
        return [$startTime, $endTime, $nextEndTime];
    }

    public static function gen_code($user_id = 0){
        $model = new \app\common\model\InviteCode();
        $code = $model->where("user_id", $user_id)->value('code');
        if($code && $user_id){
            return $code;
        }else{
            $code = 0;
            //查询未启用的若干code
            $codes = $model->alias('ic')->where("user_id", 0)->limit(100)->whereNotExists(function ($query) use ($model) {
                $query->name('user')->alias('u')->where('u.id = ic.code');
            })->column('code');
            // var_dump($model->getLastSql());die;
            $is_gen_new = true;
            if($codes){
                if(count($codes) > 50){
                    $is_gen_new = false;
                }

                $random_key = array_rand($codes, 1);
                $code = $codes[$random_key];
                $model->where('code', $code)->update(['user_id' => $user_id]);
            }
            //生成新codes
            if(!$code || $is_gen_new){
                $max_code = $model->limit(1)->max('code');
                if(!$max_code){
                    $max_code = 100000;
                }

                $insert_all = [];
                for ($i = 1, $j = $max_code + 1; $i < 1000; $i++,$j++){
                    $insert_all[] = ['code' => $j];
                }
//                var_dump($insert_all);die;
                $model->insertAll($insert_all);
            }
            if($code){
                return $code;
            }else{
                return self::gen_code($user_id);
            }
        }
    }
}